﻿using System;
using System.Threading;

namespace eLoop;

sealed class ThreadPoolScheduler : ITaskScheduler
{
    public string Id => "thread_pool_0";
    public int ThreadId => 0;
    public string Name => "thread_pool";
    public long RefCount => 0;
    public bool IsDisposed => false;

    public void Reference() { }
    public void Unreference() { }
    
    public bool IsEquals(ITaskScheduler scheduler) => false;
    
    public void Schedule(IRunnable runnable, object o)
    {
        this.Schedule1(state => { runnable.Execute(state); }, o);
    }

    public unsafe void Schedule(delegate*<object, void> action, object o)
    {
        this.Schedule0((state) => { action(state); }, o);
    }

    public void Schedule(IThreadPoolExecutor executor)
    {
#if NETSTANDARD2_0 || NETSTANDARD2_1
        this.Schedule1((o) => { executor.Execute(); }, null);
#elif NETCOREAPP
        ThreadPool.UnsafeQueueUserWorkItem(executor, preferLocal: false);
#endif
    }

    public void Schedule0(WaitCallback action, object o)
    {
        ThreadPool.UnsafeQueueUserWorkItem(action, o);
    }

    public void Schedule1(Action<object> action, object o)
    {
#if NETSTANDARD2_0 || NETSTANDARD2_1
        ThreadPool.QueueUserWorkItem(s =>
        {
            var tuple = (Tuple<Action<object>, object>)s;
            tuple.Item1(tuple.Item2);
        },
        Tuple.Create(action, o));
#elif NETCOREAPP
        ThreadPool.UnsafeQueueUserWorkItem(action, o, preferLocal: false);
#endif
    }

    public void Dispose() { }
}